﻿using System;
using System.Collections.Generic;
using System.Linq;
using Urs.Core;
using Urs.Core.Data;
using Urs.Data;
using Urs.Data.Domain.Coupons;

namespace Urs.Services.Coupons
{
    public partial class CouponService : ICouponService
    {
        #region Fields
        private readonly IRepository<Coupon> _couponRepository;
        private readonly IDbContext _dbContext;
        private readonly IDataProvider _dataProvider;
        private readonly IRepository<CouponUserMapping> _couponUserRepository;

        #endregion

        #region ctors
        public CouponService(IRepository<Coupon> couponRepository, 
            IDbContext dbContext,
            IDataProvider dataProvider,
            IRepository<CouponUserMapping> couponUserRepository)
        {
            this._couponRepository = couponRepository;
            this._dbContext = dbContext;
            this._dataProvider = dataProvider;
            this._couponUserRepository = couponUserRepository;
        }
        #endregion

        #region  coupon method
        public void InsertCoupon(Coupon coupon)
        {
            if (coupon == null)
                throw new ArgumentNullException("coupon");

            _couponRepository.Insert(coupon);

        }
        public void UpdateCoupon(Coupon coupon)
        {
            if (coupon == null)
                throw new ArgumentNullException("coupon");

            _couponRepository.Update(coupon);

        }

        public void DeleteCoupon(Coupon coupon)
        {
            if (coupon == null)
                throw new ArgumentNullException("coupon");

            _couponRepository.Delete(coupon);

        }

        public virtual Coupon GetCouponById(int id)
        {
            var query = _couponRepository.Table;
            query = query.Where(q => q.Id == id);

            var coupon = query.FirstOrDefault();
            return coupon;
        }

        public virtual IPagedList<Coupon> GetCoupon(DateTime? startTime, DateTime? endTime, Decimal? miniumConsume, int PageIndex, int PageSize)
        {
            var query = _couponRepository.Table;

            if (startTime.HasValue)
                query = query.Where(q => q.StartTime >= startTime);

            if (endTime.HasValue)
                query = query.Where(q => q.EndTime <= endTime);

            if (miniumConsume.HasValue)
                query = query.Where(q => q.MinimumConsumption == miniumConsume);

            query = query.OrderByDescending(q => q.Id);

            var coupons = new PagedList<Coupon>(query, PageIndex, PageSize);
            return coupons;
        }

        public virtual IList<Coupon> GetUsableCoupons(int userId, decimal subTotal)
        {
            var query = (from c in _couponRepository.Table
                         join cc in _couponUserRepository.Table on c.Id equals cc.CouponId
                         where cc.UserId == userId && cc.IsUsed == false
                         select c);

            query = query.Where(q => q.StartTime <= DateTime.Now && q.EndTime >= DateTime.Now);

            query = query.Where(q => (!q.IsAmountLimit) || (q.IsAmountLimit && q.UsedAmount < q.Amount));

            query = query.Where(q => q.MinimumConsumption <= subTotal);

            query = query.OrderByDescending(q => q.Id);

            return query.ToList();
        }

        public Coupon GetUsableCoupon(int userId, decimal subTotal, int couponId)
        {
            var list = GetUsableCoupons(userId, subTotal);
            var item = list.FirstOrDefault(q => q.Id == couponId);
            return item;
        }

        #endregion

        #region 绑定优惠券
        public virtual bool InsertCouponUser(CouponUserMapping couponUser)
        {
            if (couponUser == null)
                throw new ArgumentNullException("couponUser");
            var coupon = GetCouponById(couponUser.CouponId);
            int Couponamount = coupon.Amount;
            int useAcount = GetCouponsOrUser(null, null, couponUser.CouponId, 0, int.MaxValue).Count;
            if (CouponAmount(Couponamount, useAcount) && coupon.UsedAmount >= 0 || !coupon.IsAmountLimit)
            {
                try
                {
                    _couponUserRepository.Insert(couponUser);
                    coupon.UsedAmount += 1;
                    UpdateCoupon(coupon);

                }
                catch (Exception xx)
                {
                    throw xx;
                }
                return true;
            }
            return false;
        }

        public virtual bool CouponAmount(int CouponAmount, int useAcount)
        {
            bool right = false;
            if (CouponAmount > useAcount)
            {
                right = true;
            }
            return right;
        }
        public virtual void UpdateCouponUser(CouponUserMapping couponUser)
        {
            if (couponUser == null)
                throw new ArgumentNullException("couponUser");
            _couponUserRepository.Update(couponUser);
        }
        public CouponUserMapping GetCouponUserById(int id)
        {
            return _couponUserRepository.GetById(id);
        }
        public virtual CouponUserMapping GetCouponUser(int userId, int couponId)
        {
            var query = _couponUserRepository.Table;

            query = query.Where(q => q.UserId == userId && q.CouponId == couponId);

            return query.FirstOrDefault();
        }

        public virtual IList<CouponUserMapping> GetCouponUser(int userId)
        {
            var query = from couponUser in _couponUserRepository.Table
                        join coupon in _couponRepository.Table on couponUser.CouponId equals coupon.Id
                        where (coupon.StartTime < DateTime.Now) && (coupon.EndTime > DateTime.Now)
                        select couponUser;

            query = query.Where(q => q.UserId == userId && q.IsUsed == false);

            return query.ToList();
        }

        public virtual void DeleteCouponUser(CouponUserMapping couponUser)
        {
            if (couponUser == null)
                throw new ArgumentNullException("couponUser");
            _couponUserRepository.Delete(couponUser);
        }
        public virtual IPagedList<CouponUserMapping> GetCouponsOrUser(int? userId, int? type, int? couponId, int PageIndex, int pageSize)
        {
            var query = _couponUserRepository.Table;
            if (userId.HasValue)
                query = query.Where(q => q.UserId == userId);
            if (type.HasValue && type > 0)
            {
                DateTime now = DateTime.Today.AddDays(1);
                switch (type)
                {
                    case 1:
                        query = query.Where(q => q.Coupon.EndTime < now);   //过期的
                        break;
                    case 2:
                        query = query.Where(q => q.Coupon.EndTime >= now);
                        break;
                }
            }
            if (couponId.HasValue)
                query = query.Where(q => q.CouponId == couponId);

            query = query.OrderByDescending(q => q.Id);
            var a = new PagedList<CouponUserMapping>(query, PageIndex, pageSize);
            return a;
        }
        public IList<Coupon> GetValidCoupon(int userId, decimal price)
        {
            var dt = DateTime.Today;
            var query = from cc in _couponUserRepository.Table
                        join c in _couponRepository.Table on cc.CouponId equals c.Id
                        where (c.EndTime >= dt) &&
                        (c.StartTime <= dt) && !cc.IsUsed && cc.UserId == userId && price >= c.MinimumConsumption
                        select c;

            return query.ToList();
        }

        #endregion


    }
}
